/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Andi
 */
public class server {
    // member
    private ServerSocket serverSock;
    private DB database = new DB();
    private int port=10000;
    private String prefixPath = "D:/tesgan/server";

    public server() throws IOException{
        serverSock = new ServerSocket(port);
        database = new DB();
    }
    public void startServer() throws SQLException{
        while (true){
            try {
                System.out.println("Memulai server ...");
                while (true) {//nunggu koneksi dengan client
                    clientHandler s = new clientHandler(serverSock.accept());
                    s.start();//bikin thread baru setelah accept dengan client
                }
            } catch (IOException ex) {
                Logger.getLogger(server.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    class clientHandler extends Thread{
        Socket clientSock;
        DataInputStream din;
        DataOutputStream dout;
        Long timeLastUpdate;

        clientHandler(Socket soc) throws IOException {//konstruktor
            clientSock = soc;
            din = new DataInputStream(clientSock.getInputStream());
            dout = new DataOutputStream(clientSock.getOutputStream());
            System.out.println("client " + clientSock.getLocalAddress().getHostAddress() + ":" + clientSock.getPort() + " terkoneksi..");
            //baca time last update
            //timeLastUpdate = din.readLong();//nerima dari Client, kemudian ke method run
        }

        public void handshake() throws IOException{
            String handshake = din.readUTF();
            System.out.println("Message handshake yang diterima = " + handshake);
            String pstr = "DOBOG protocol";
            if(handshake.equalsIgnoreCase(pstr)){
                dout.writeUTF(pstr);
                dout.flush();
            }
        }

        public boolean loginHandler() throws IOException, SQLException{
            String autentikasi = din.readUTF();
            String[] temp = autentikasi.split("\\|");
            System.out.println("username = "+temp[0]);
            System.out.println("password = "+temp[1]);
            if (database.ceklogin(temp[0], temp[1])){
                dout.writeUTF("ACK");
                return true;
            }else{
                dout.writeUTF("NACK");
                clientSock.close();
                return false;
            }
        }

        public void sendFile(File f) throws Exception {
            try {
                dout.writeLong(f.length());
                FileInputStream fin = new FileInputStream(f);
                byte[] _byte = new byte[1024];
                int length;
                do {
                    length = fin.read(_byte);
                    if (length != -1) {
                        dout.write(_byte, 0, length);
                    }
                } while (length != -1);
                fin.close();
                String diterima = din.readUTF();
                if (diterima.startsWith("OK")) {
                    //berhasil
                } else {
                    //gagal
                    System.out.println(diterima);
                    throw new Exception("gagal mengirim");
                }
            } catch (Exception e) {
                if (!e.getMessage().equals("file sudah ada")) {
                    throw e;
                }
            }
        }

        public void receiveFile(File f) throws Exception {
            long size = din.readLong();
            FileOutputStream fout = new FileOutputStream(f);
            int length;
            byte[] _byte = new byte[1024];
            long byteread = 0;
            while (byteread < size) {
                length = din.read(_byte);
                if (length != -1) {
                    fout.write(_byte, 0, length);
                    byteread += length;
                }
            }
            fout.close();
            //kirim OK
            dout.writeUTF("OK\n");
            dout.flush();
        }


        @Override
        public void run() {
            try {
                handshake();
                if (loginHandler()){
                    System.out.println("autentikasi diterima");
                    // RESPONSE LIST FILES
                    System.out.println("RESPONSE LIST FILES");
                    String messageRequestListFiles = din.readUTF();
                    String[] temp = messageRequestListFiles.split("\\|");
                    ArrayList<InfoFile> listInfoFiles = new ArrayList<InfoFile>();
                    listInfoFiles = database.getFileUser(temp[1]);
                    String responseListFiles = "";
                    for(int i=0; i<listInfoFiles.size(); i++){
                        responseListFiles = responseListFiles + listInfoFiles.get(i).convertToMessageInfoFile();
                    }
                    System.out.println(responseListFiles);
                    dout.writeUTF(responseListFiles);
                    dout.flush();
                    // menerima balasan request file dari client
                    String messageRequestClient = din.readUTF();
                    System.out.println("message dari client \n"+messageRequestClient);
                    String[] arg = messageRequestClient.split("\\|");
                    String feedBack;
                    String path = prefixPath + "/" + arg[1] + "/" + arg[2];
                    long dateModified = Long.parseLong(arg[3]);
                    System.out.println("File path = " + path);
                    File myFile = new File(path);
                    if (arg[0].equalsIgnoreCase("requestDownloadFile")){
                        sendFile(myFile);
                        feedBack = din.readUTF(); // perlu pengecekan lagi???
                        System.out.println("Feedback dari client setelah requestDownloadFile = " + feedBack);
                    }else if (arg[0].equalsIgnoreCase("requestUploadFile")){
                        String messageToClient = "uploadStart";
                        dout.writeUTF(messageToClient);
                        dout.flush();
                        receiveFile(myFile);
                        System.out.println("andi dewa");
                        dout.writeUTF("OK");
                        if (database.isFileExist(arg[2])){ // jika di server sudah ada
                            database.editFile(arg[2], dateModified);
                        }else{
                            database.addFile(arg[2], path, dateModified, arg[1]);
                        }
                    }else if (arg[0].equalsIgnoreCase("requestDeleteFile")){
                        boolean deleted = myFile.delete();
                        database.deleteFile(arg[2]);
                        if (deleted){
                            dout.writeUTF("deleteFinished");
                        }
                    }else if(messageRequestClient.equalsIgnoreCase("logout")){
                        dout.writeUTF("logout");
                        dout.flush();
                    }
                }
                din.close();
                dout.close();
                clientSock.close();
            } catch (Exception e) {
            }
        }

    }


    public static void main(String[] args) throws IOException, SQLException{
        server Server = new server();
        Server.startServer();
        System.out.println("END");
    }
}
